package com.hk.utils;

import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;

import java.security.SecureRandom;
import java.util.Arrays;

public class PBKDF2Utils {
    private static final int ITERATIONS = 10000; // 迭代次数，可根据需求调整，越大越安全但耗时越长
    private static final int KEY_LENGTH = 256; // 生成密钥长度，单位bit

    public static byte[] pbkdf2(String password, byte[] salt) {
        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator();
        gen.init(password.getBytes(), salt, ITERATIONS);
        return ((KeyParameter) gen.generateDerivedParameters(KEY_LENGTH)).getKey();
    }

    public static String encodePassword(String password) {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);
        byte[] hash = pbkdf2(password, salt);
        byte[] hashBytes = new byte[salt.length + hash.length];
        System.arraycopy(salt, 0, hashBytes, 0, salt.length);
        System.arraycopy(hash, 0, hashBytes, salt.length, hash.length);
        return bytesToHex(hashBytes);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static boolean verifyPassword(String password, String hashedPassword) {
        byte[] hashBytes = hexToBytes(hashedPassword);
        if (hashBytes.length < 16 * 2) {
            throw new IllegalArgumentException("Hashed password length is insufficient.");
        }
        byte[] salt = Arrays.copyOfRange(hashBytes, 0, 16);
        byte[] storedHash = Arrays.copyOfRange(hashBytes, 16, hashBytes.length);
        byte[] newHash = pbkdf2(password, salt);
        return Arrays.equals(storedHash, newHash);
    }

    private static byte[] hexToBytes(String hex) {

        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}
